#define CODE_ANALYSIS

using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.IO;
using System.Windows.Forms;
using DbSetupHelper.Common;
using DbSetupHelper.Common.Exceptions;
using DbSetupHelper.Business;
using DbSetupHelper.Plugin.ScriptPackage;
using System.Collections.ObjectModel;


[assembly: CLSCompliant(true)]
namespace DbSetupHelper
{
    /// <summary>
    /// Main entry point of the program.
    /// </summary>
    static class Program
    {
        /// <summary>
        /// Main entry point of the program.
        /// </summary>
        /// <param name="args">Arguments supplied by the user.</param>
        /// <remarks>
        /// Run without parameters to get help.
        /// </remarks>
        [SuppressMessage("Microsoft.Globalization", "CA1303")] //get around not using resource files.
        [STAThread]
        static void Main(string[] args)
        {
#if(DEBUG)
            Console.Out.WriteLine("Args are as follows:");
            foreach (string arg in args)
            {
                Console.Out.Write(arg);
                Console.Out.Write(" ");
            }
            Console.Out.WriteLine();
            Console.Out.WriteLine("Press any key to continue.");
            Console.In.ReadLine();
#endif

            InstallParameters installParms = ParseCommandLineArgs(args);

            if (installParms.ShowHelp)
            {
                PrintHelp();
            }
            else
            {
                if (installParms.InteractiveInstall)
                {
                    Console.Out.WriteLine("Starting interactive mode, please wait.");

                    //Collect any information from the user. 
                    SettingsDialog settingsDialog = new SettingsDialog(installParms);
                    if (settingsDialog.ShowDialog() == DialogResult.OK)
                    {
                        //migrate these settings to the install parms
                        installParms = settingsDialog.GenerateUserInstallParameters();
                    }

                    //clean up our dialog box.
                    settingsDialog.Dispose();
                }
                else
                {
                    IScriptPackageMetadata packageMetadata = null;

                    Collection<IScriptPackageMetadata> packages = 
                        DatabaseController.Instance.FetchAvailableDbScriptPackages();

                    foreach (IScriptPackageMetadata metadata in packages)
                    {
                        if (metadata.InitialDatabaseCreation)
                        {
                            if (packageMetadata == null)
                            {
                                packageMetadata = metadata;
                            }
                            else
                            {
                                if (metadata.ScriptPackageVersion > packageMetadata.ScriptPackageVersion)
                                    packageMetadata = metadata;
                            }
                        }
                    }

                    installParms.ScriptPackageAssembly = 
                        DatabaseController.Instance.FetchAssemblyForScriptPackage(packageMetadata.PackageFriendlyName);
                    installParms.ScriptPattern = 
                        DatabaseController.Instance.FetchDbScriptsForPackage(packageMetadata.PackageFriendlyName);
                }

                //move extract only check to business logic.
                if (!installParms.CancelInstall)
                {
                    if (installParms.ScriptPackageAssembly != null)
                    {
                        RunParameters runParms = DatabaseController.Instance.
                            FetchDefaultRunParameteresForPackage(installParms.ScriptPackageAssembly);

                        if (string.IsNullOrEmpty(installParms.Server))
                            installParms.Server = runParms.SqlServer;
                        if (string.IsNullOrEmpty(installParms.User))
                            installParms.User = runParms.UserName;
                        if (string.IsNullOrEmpty(installParms.Password))
                            installParms.Password = runParms.Password;
                    }

                    DatabaseController.Instance.OnMessage += new EventHandler<MessageEventArgs>(DatabaseController_OnMessage);
                    DatabaseController.Instance.Run(installParms);
                }

                if (installParms.DebugMode)
                {
                    Console.Out.WriteLine("Please press enter to exit.");
                    Console.In.ReadLine();
                }
            }
        }

        static void DatabaseController_OnMessage(object sender, MessageEventArgs e)
        {
            Console.Out.WriteLine(e.Message);
        }

        private static InstallParameters ParseCommandLineArgs(string[] args)
        {
            InstallParameters installParms = new InstallParameters();

            for (int i = 0; i < args.Length; i = i + 2)
            {
                switch (args[i])
                {
                    case "-db":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.DbName = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-dbp":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.DbUserPassword = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-dbu":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.DbUserName = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-e":
                        if (args.Length > i + 1
                            && !args[i + 1].StartsWith("-"))
                        {
                            installParms.ExtractOnly = bool.Parse(args[i + 1]);
                        }
                        else
                        {
                            installParms.ExtractOnly = true;
                            i--;
                        }
                        break;
                    case "-p":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.Password = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-s":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.Server = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-t":
                        if (args.Length > i + 1
                            && !args[i + 1].StartsWith("-"))
                        {
                            installParms.TestInstall = bool.Parse(args[i + 1]);
                        }
                        else
                        {
                            installParms.TestInstall = false;
                            i--;
                        }
                        break;
                    case "-u":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.User = args[i + 1];
                        }
                        else
                        {
                            throw new MisusedArgumentException();
                        }
                        break;
                    case "-U":
                        if (args.Length > i + 1
                                && !args[i + 1].StartsWith("-"))
                        {
                            installParms.InteractiveInstall = !bool.Parse(args[i + 1]);
                        }
                        else
                        {
                            installParms.InteractiveInstall = true;
                            i--;
                        }
                        break;
                    case "-DEBUG":
                        installParms.DebugMode = true;
                        i--;
                        break;
                    case "/?":
                    default:
                        installParms.ShowHelp = true;
                        break;
                }
            }
            return installParms;
        }

        private static void PrintHelp()
        {
            Console.Out.WriteLine("Help:");
            Console.Out.WriteLine();
            Console.Out.WriteLine(" /?  ------ Prints this help message.");
            Console.Out.WriteLine(" -db  ----- Database Name. Database name to be used during script run.");
            Console.Out.WriteLine(" -dbu  ---- Database User. Username to be created during script run.");
            Console.Out.WriteLine(" -dbp  ---- Database User Password. Password for the DB User.");
            Console.Out.WriteLine(" -e  ------ Extract Only. Exits application after extract from MSI.");
            Console.Out.WriteLine(" -p  ------ Password. Password for specified user.");
            Console.Out.WriteLine(" -s  ------ Server. Server to connect to for scripts to run against.");
            Console.Out.WriteLine(" -t  ------ Test Install. Runs optional test scripts as well.");
            Console.Out.WriteLine(" -u  ------ User name. User name to connect to SQL database with.");
            Console.Out.WriteLine(" -U  ------ Unattended. Runs the system without prompting for user input.");
            Console.Out.WriteLine(" -DEBUG  -- Pipes all output to the command window and halts before exit.");
            Console.Out.WriteLine();
            Console.Out.WriteLine(" e.g.");
            Console.Out.WriteLine("  DBSetupHelper -u user -p password -s CompName\\SQLEXPRESS");
            Console.Out.WriteLine("  DBSetupHelper -i true");
            Console.Out.WriteLine("  DBSetupHelper -u user -p password -i true");
            Console.Out.WriteLine("  DBSetupHelper -u user -p password -i true -t true");
            Console.Out.WriteLine();
        }
    }
}
